package com.carrental.integration.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.carrental.integration.client.BaiduMapClient;
import com.carrental.integration.service.MapService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

/**
 * 百度地图服务实现类
 * 通过调用百度地图API实现地图服务功能
 */
@Slf4j
@Service
public class BaiduMapServiceImpl implements MapService {

    @Resource
    private BaiduMapClient baiduMapClient;

    @Value("${third-party.map.baidu.api-key}")
    private String apiKey;

    private static final String OUTPUT_FORMAT = "json";
    private static final double EARTH_RADIUS = 6371000; // 地球半径，单位米

    /**
     * 地理编码，将地址信息转换为经纬度坐标
     *
     * @param address 地址信息
     * @return 包含经纬度坐标的Map对象
     */
    @Override
    public Map<String, Object> geocoding(String address) {
        try {
            String result = baiduMapClient.geocoding(address, OUTPUT_FORMAT, apiKey);
            log.info("百度地图地理编码API返回结果：{}", result);
            
            JSONObject jsonResult = JSON.parseObject(result);
            if (jsonResult.getInteger("status") == 0) {
                JSONObject location = jsonResult.getJSONObject("result").getJSONObject("location");
                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put("latitude", location.getDouble("lat"));
                resultMap.put("longitude", location.getDouble("lng"));
                resultMap.put("precise", jsonResult.getJSONObject("result").getInteger("precise"));
                resultMap.put("confidence", jsonResult.getJSONObject("result").getInteger("confidence"));
                resultMap.put("level", jsonResult.getJSONObject("result").getString("level"));
                return resultMap;
            } else {
                log.error("百度地图地理编码API调用失败，状态码：{}，错误信息：{}", 
                        jsonResult.getInteger("status"), jsonResult.getString("message"));
                return new HashMap<>();
            }
        } catch (Exception e) {
            log.error("调用百度地图地理编码API异常", e);
            return new HashMap<>();
        }
    }

    /**
     * 逆地理编码，将经纬度坐标转换为地址信息
     *
     * @param latitude 纬度
     * @param longitude 经度
     * @return 包含地址信息的Map对象
     */
    @Override
    public Map<String, Object> reverseGeocoding(double latitude, double longitude) {
        try {
            String location = latitude + "," + longitude;
            String result = baiduMapClient.reverseGeocoding(location, OUTPUT_FORMAT, apiKey);
            log.info("百度地图逆地理编码API返回结果：{}", result);
            
            JSONObject jsonResult = JSON.parseObject(result);
            if (jsonResult.getInteger("status") == 0) {
                JSONObject resultObj = jsonResult.getJSONObject("result");
                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put("formatted_address", resultObj.getString("formatted_address"));
                resultMap.put("business", resultObj.getString("business"));
                resultMap.put("addressComponent", resultObj.getJSONObject("addressComponent"));
                resultMap.put("pois", resultObj.getJSONArray("pois"));
                return resultMap;
            } else {
                log.error("百度地图逆地理编码API调用失败，状态码：{}，错误信息：{}", 
                        jsonResult.getInteger("status"), jsonResult.getString("message"));
                return new HashMap<>();
            }
        } catch (Exception e) {
            log.error("调用百度地图逆地理编码API异常", e);
            return new HashMap<>();
        }
    }

    /**
     * 路径规划，计算两点间的驾车路线
     *
     * @param originLat 起点纬度
     * @param originLng 起点经度
     * @param destLat 终点纬度
     * @param destLng 终点经度
     * @return 包含路径规划结果的Map对象
     */
    @Override
    public Map<String, Object> drivingDirection(double originLat, double originLng, double destLat, double destLng) {
        try {
            String origin = originLat + "," + originLng;
            String destination = destLat + "," + destLng;
            String result = baiduMapClient.drivingDirection(origin, destination, OUTPUT_FORMAT, apiKey);
            log.info("百度地图路径规划API返回结果：{}", result);
            
            JSONObject jsonResult = JSON.parseObject(result);
            if (jsonResult.getInteger("status") == 0) {
                JSONObject resultObj = jsonResult.getJSONObject("result");
                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put("routes", resultObj.getJSONArray("routes"));
                
                // 提取第一条路线的距离和时间
                if (resultObj.getJSONArray("routes").size() > 0) {
                    JSONObject firstRoute = resultObj.getJSONArray("routes").getJSONObject(0);
                    resultMap.put("distance", firstRoute.getInteger("distance"));
                    resultMap.put("duration", firstRoute.getInteger("duration"));
                }
                
                return resultMap;
            } else {
                log.error("百度地图路径规划API调用失败，状态码：{}，错误信息：{}", 
                        jsonResult.getInteger("status"), jsonResult.getString("message"));
                return new HashMap<>();
            }
        } catch (Exception e) {
            log.error("调用百度地图路径规划API异常", e);
            return new HashMap<>();
        }
    }

    /**
     * 地点检索，根据关键字检索地点
     *
     * @param keyword 检索关键字
     * @param region 检索区域
     * @return 包含地点检索结果的Map对象
     */
    @Override
    public Map<String, Object> placeSearch(String keyword, String region) {
        try {
            String result = baiduMapClient.placeSearch(keyword, region, OUTPUT_FORMAT, apiKey);
            log.info("百度地图地点检索API返回结果：{}", result);
            
            JSONObject jsonResult = JSON.parseObject(result);
            if (jsonResult.getInteger("status") == 0) {
                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put("total", jsonResult.getInteger("total"));
                resultMap.put("results", jsonResult.getJSONArray("results"));
                return resultMap;
            } else {
                log.error("百度地图地点检索API调用失败，状态码：{}，错误信息：{}", 
                        jsonResult.getInteger("status"), jsonResult.getString("message"));
                return new HashMap<>();
            }
        } catch (Exception e) {
            log.error("调用百度地图地点检索API异常", e);
            return new HashMap<>();
        }
    }

    /**
     * 计算两点间的距离
     * 使用Haversine公式计算球面两点间的距离
     *
     * @param originLat 起点纬度
     * @param originLng 起点经度
     * @param destLat 终点纬度
     * @param destLng 终点经度
     * @return 两点间的距离，单位为米
     */
    @Override
    public double calculateDistance(double originLat, double originLng, double destLat, double destLng) {
        // 优先使用百度地图API计算实际驾车距离
        Map<String, Object> directionResult = drivingDirection(originLat, originLng, destLat, destLng);
        if (!directionResult.isEmpty() && directionResult.containsKey("distance")) {
            return Double.parseDouble(directionResult.get("distance").toString());
        }
        
        // 如果API调用失败，使用Haversine公式计算直线距离
        double latDistance = Math.toRadians(destLat - originLat);
        double lngDistance = Math.toRadians(destLng - originLng);
        
        double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
                + Math.cos(Math.toRadians(originLat)) * Math.cos(Math.toRadians(destLat))
                * Math.sin(lngDistance / 2) * Math.sin(lngDistance / 2);
        
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        
        return EARTH_RADIUS * c;
    }

    /**
     * 计算两点间的驾车时间
     *
     * @param originLat 起点纬度
     * @param originLng 起点经度
     * @param destLat 终点纬度
     * @param destLng 终点经度
     * @return 两点间的驾车时间，单位为秒
     */
    @Override
    public int calculateDrivingTime(double originLat, double originLng, double destLat, double destLng) {
        Map<String, Object> directionResult = drivingDirection(originLat, originLng, destLat, destLng);
        if (!directionResult.isEmpty() && directionResult.containsKey("duration")) {
            return Integer.parseInt(directionResult.get("duration").toString());
        }
        
        // 如果API调用失败，使用估算方法（假设平均车速为60km/h）
        double distance = calculateDistance(originLat, originLng, destLat, destLng);
        return (int) (distance / 16.67); // 16.67 m/s ≈ 60 km/h
    }
} 